package com.wyw.core.config.support;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import net.sf.ehcache.Cache;

import org.apache.commons.lang.StringUtils;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

import com.wyw.base.util.BaseUtil;
import com.wyw.core.config.XmlConfigParse;
import com.wyw.core.exception.WYWException;
import com.wyw.core.secu.dto.XmlConfigType;
import com.wyw.core.util.CacheManager;
import com.wyw.core.workflow.WorkflowConstant;
import com.wyw.core.workflow.dto.processdef.ActivityDto;
import com.wyw.core.workflow.dto.processdef.AttachmentDto;
import com.wyw.core.workflow.dto.processdef.DecisionDto;
import com.wyw.core.workflow.dto.processdef.ProcessDefinitionDto;
import com.wyw.core.workflow.dto.processdef.ProcessDefinitionVersionDto;
import com.wyw.core.workflow.dto.processdef.ReportDto;
import com.wyw.core.workflow.dto.processdef.TaskListQueryDto;

public class ProcessDefinitionParse implements XmlConfigParse{

	@Override
	public void parse(XmlConfigType xmlConfigType, Document xmlConfig) throws Exception {
		// TODO Auto-generated method stub
		List<Element> processConfigXmlList=xmlConfig.getRootElement().getChildren();
		HashMap processConfigMap = new HashMap();
		ProcessDefinitionDto processDefinition;
		for(Element processConfig :processConfigXmlList){
			processDefinition = parseProcessDefinition(processConfig);
			if(processConfigMap.containsKey(processDefinition.getBizTypeCode())){
				throw new WYWException("bizTypeCode："+processDefinition.getBizTypeCode()+"的业务流程重复加载");
			}else{
				processConfigMap.put(processDefinition.getBizTypeCode(), processDefinition);
			}
		}
		net.sf.ehcache.Element processDefinitionMap=new  net.sf.ehcache.Element(CacheManager.process_definition_map,processConfigMap);
		CacheManager.put(processDefinitionMap);
	}
	
	private ProcessDefinitionDto parseProcessDefinition(Element processConfig) throws WYWException{
		ProcessDefinitionDto processDefinition = new ProcessDefinitionDto ();
		String bizTypeCode = processConfig.getAttributeValue("bizTypeCode");
		if(StringUtils.isEmpty(bizTypeCode)){
			throw new WYWException("bizTypeCode：业务类型代码不能为空");
		}
		
		
		processDefinition.setBizTypeCode(bizTypeCode);
		String processDefinitionCode = processConfig.getChildText("processDefinitionCode");
		processDefinition.setProcessDefinitionCode(processDefinitionCode);
		String processDefinitionName = processConfig.getChildText("processDefinitionName");
		processDefinition.setProcessDefinitionName(processDefinitionName);
		String startStrategic = processConfig.getChildText("startStrategic");
		processDefinition.setStartStrategic(startStrategic);
		
		String bizOverView = processConfig.getChildText("bizOverView");
		if(StringUtils.isNotEmpty(bizOverView)){
			processDefinition.setBizOverView(bizOverView);
		}
		
		String processHandleClass = processConfig.getChildText("processHandleClass");
		if(StringUtils.isNotEmpty(processHandleClass)){
			processDefinition.setProcessHandleClass(processHandleClass);
		}else{
			throw new WYWException("业务类型:"+bizTypeCode+"业务处理类不能为空");
		}
		
		parseTaskListQuery( processDefinition ,processConfig.getChild("taskListQuery"));
		
		Element processHandleRole = processConfig.getChild("processHandleRole");
		if(processHandleRole !=null){
			String startRole = processHandleRole.getChildText("startRole");
			processDefinition.setStartRole(startRole);
			String viewRoleList = processHandleRole.getChildText("viewRoleList");
			processDefinition.setViewRoleList(BaseUtil.splitAsList(viewRoleList, ","));
		}
		
		String bizFlowDict = processConfig.getChildText("bizFlowDict");
		processDefinition.setBizFlowDict(bizFlowDict);
		
		String bizStatusDict = processConfig.getChildText("bizStatusDict");
		processDefinition.setBizStatusDict(bizStatusDict);
		
		String isInitialBizHandle = processConfig.getChildText("isInitialBizHandle");
		if(StringUtils.isNotEmpty(isInitialBizHandle)){
			processDefinition.setIsInitialBizHandle(new Boolean(isInitialBizHandle));
		}
		
		String isInitialBizDesc = processConfig.getChildText("isInitialBizDesc");
		if(StringUtils.isNotEmpty(isInitialBizHandle)){
			processDefinition.setIsInitialBizDesc(new Boolean(isInitialBizDesc));
		}
		
		String msgTemplateGroup = processConfig.getChildText("msgTemplateGroup");
		processDefinition.setMsgTemplateGroup(msgTemplateGroup);
		try{
			HashMap versions = parseVersions(processConfig.getChild("versions"));
			processDefinition.setVersions(versions);
		}catch(Exception e){
			throw new WYWException("bizTypeCode："+bizTypeCode+"解析异常",e);
		}
		return processDefinition ;
	}
	
	private void parseTaskListQuery(ProcessDefinitionDto processDefinition ,Element taskListQuery){
		if(taskListQuery !=null){
			TaskListQueryDto taskListQueryDto = new TaskListQueryDto();
			taskListQueryDto.setPageView(taskListQuery.getChildText("pageView"));
			taskListQueryDto.setTaskListDefine(taskListQuery.getChildText("taskListDefine"));
			processDefinition.setTaskListQuery(taskListQueryDto);
		}
		
	}
	
	private HashMap parseVersions(Element versionsElement)throws Exception{
		List<Element> versionList = versionsElement.getChildren();
		HashMap versions = new HashMap();
		ProcessDefinitionVersionDto processDefinitionVersionDto;
		for(Element  versionElement : versionList){
			processDefinitionVersionDto = parseVersion(versionElement);
			versions.put(processDefinitionVersionDto.getVersionSign(), processDefinitionVersionDto);
		}
		return versions;
	}
	
	private ProcessDefinitionVersionDto parseVersion(Element versionElement)throws Exception{
		ProcessDefinitionVersionDto processDefinitionVersionDto = new ProcessDefinitionVersionDto();
		
		String versionSign = versionElement.getChildText("versionSign");
		processDefinitionVersionDto.setVersionSign(versionSign);
		
		Element linkActivitiesElement = versionElement.getChild("linkActivities");
		if(linkActivitiesElement != null){
			List linkActivities = parseLinkActivitiesList(linkActivitiesElement.getChildren("group"));
			processDefinitionVersionDto.setLinkActivities(linkActivities);
		}
		
		
		HashMap activities = parseActivitiesList(versionElement.getChild("activities"));
		processDefinitionVersionDto.setActivities(activities);
		
		List reportList = parseReportList(versionElement.getChild("reportList"));
		processDefinitionVersionDto.setReportList(reportList);
	 
		return processDefinitionVersionDto;
	}
	
	
	private List parseReportList(Element reportListElement){
		if(reportListElement == null){
			return null;
		}
		List reportList = new ArrayList();
		List<Element> reportElementList = reportListElement.getChildren("report");
		ReportDto reportDto ;
		String roles;
		for(Element reportElement:reportElementList){
			 reportDto = new ReportDto();
			 reportDto.setCode(reportElement.getAttributeValue("code"));
			 roles=reportElement.getAttributeValue("roles");
			 reportDto.setRoles(BaseUtil.splitAsList(roles, ","));
			 reportList.add(reportDto);
		}
		
		return reportList;
	}
	
	private HashMap parseActivitiesList(Element activitiesElement)throws Exception{
		HashMap activitiesMap = new HashMap();
		List<Element> activitiesElementList = activitiesElement.getChildren("activity");
		ActivityDto activityDto;
		for(Element activityElement : activitiesElementList){
			activityDto = parseActivity( activitiesMap , activityElement);
			activitiesMap.put(activityDto.getActivityName(), activityDto);
		}
		return activitiesMap ;
	}
	
	private ActivityDto parseActivity(HashMap activitiesMap ,Element activityElement)throws Exception{
		ActivityDto activityDto = new ActivityDto();
		ActivityDto refActivityDto; 
		String ref ;
		
		activityDto.setActivityName(activityElement.getAttributeValue("name")); 
		
		
		Element handleView = activityElement.getChild("activityHandleView");
		ref = handleView.getAttributeValue("ref"); 
		if(StringUtils.isNotEmpty(ref)){
			refActivityDto =(ActivityDto) activitiesMap.get(ref);
			activityDto.setHandleView(refActivityDto.getHandleView());
		}else{
			activityDto.setHandleView(handleView.getText());
		}
		
		String submitList = activityElement.getChildText("submitList");
		activityDto.setSubmitList(BaseUtil.splitAsList(submitList, ","));
		
		Element activityHandle = activityElement.getChild("activityHandle");
		Element activityHandleLoad = activityHandle.getChild("load");		
		ref = getAttValue(activityHandleLoad,"ref");
		if(StringUtils.isNotEmpty(ref)){
			refActivityDto =(ActivityDto) activitiesMap.get(ref);
			activityDto.setHandleLoad(refActivityDto.getHandleLoad());
		}else{
			activityDto.setHandleLoad(activityHandleLoad.getText());
		}
		
		Element activityHandleSave = activityHandle.getChild("save");
		ref = getAttValue(activityHandleSave,"ref");
		if(StringUtils.isNotEmpty(ref)){
			refActivityDto =(ActivityDto) activitiesMap.get(ref);
			activityDto.setHandleSave(refActivityDto.getHandleSave());
		}else{
			activityDto.setHandleSave(activityHandleSave.getText());
		}
		
		Element participant = activityElement.getChild("participant");
		String participantType = participant.getChildText("participantType");
		activityDto.setParticipantType(participantType);
		if(! participantType.equals(WorkflowConstant.wf_participant_type_user)){
			String participantCodeList = participant.getChildText("participantCodeList");
			activityDto.setParticipantCodeList(BaseUtil.splitAsList(participantCodeList, ","));
		}
		
		Element decisionList =activityElement.getChild("decisionList");
		if(decisionList != null){
			parseActivtyDecisionList(activityDto,activitiesMap,decisionList.getChildren("decision"));
		}
		
		Element attachmentList =activityElement.getChild("attachmentList");
		if(attachmentList != null){
			ref = getAttValue(attachmentList,"ref");
			if(StringUtils.isNotEmpty(ref)){
				refActivityDto =(ActivityDto) activitiesMap.get(ref);
				activityDto.setAttachmentList(refActivityDto.getAttachmentList());
			}else{
				parseActivtyAttachmentList(activityDto,activitiesMap,attachmentList.getChildren("attachment"));
			}
		}
		
		return activityDto ;
	}
	
	private void parseActivtyAttachmentList(ActivityDto activityDto,HashMap activitiesMap,List<Element> attachmentElementList)throws Exception{
		ActivityDto refActivityDto;
		List attachmentList = new ArrayList();
		AttachmentDto attachmentDto ;
		Attribute attribute;
		String ref;
		String code;
		for(Element attachment :attachmentElementList){
			ref = getAttValue(attachment,"ref");
			code = attachment.getAttributeValue("code");
			if(StringUtils.isNotEmpty(ref)){
				refActivityDto =(ActivityDto) activitiesMap.get(ref);
				List<AttachmentDto> refAttachmentList = refActivityDto.getAttachmentList();
				for(AttachmentDto tmp:refAttachmentList){
					if(tmp.getCode().equals(code)){
						attachmentList.add(tmp);
					}
				}
			}else{			
				attachmentDto = new AttachmentDto();
				attachmentDto.setCode(code);
				
				attribute=attachment.getAttribute("add");
				attachmentDto.setAdd(attribute.getBooleanValue());
				
				attribute=attachment.getAttribute("del");
				attachmentDto.setDel(attribute.getBooleanValue());
				
				attribute=attachment.getAttribute("required");
				attachmentDto.setRequired(attribute.getBooleanValue());
				
				attachmentList.add(attachmentDto);
			}
		}
		activityDto.setAttachmentList(attachmentList);
	}
	
	private void parseActivtyDecisionList(ActivityDto activityDto,HashMap activitiesMap,List<Element> decisionElementList)throws Exception{
		List decisionList = new ArrayList();
		DecisionDto decisionDto;
		Attribute attribute;
		for(Element decision:decisionElementList){
			decisionDto = new DecisionDto();
			decisionDto.setCode(decision.getAttributeValue("code"));
			attribute = decision.getAttribute("checkData");
			decisionDto.setCheckData(attribute.getBooleanValue());
			decisionList.add(decisionDto);
		}
		activityDto.setDecisionList(decisionList);
	}
	
	private String getAttValue(Element element,String attName){
		Attribute att= element.getAttribute(attName);
		if(att !=null){
			return att.getValue();
		}
		return null;
	}
	
	private List parseLinkActivitiesList(List<Element> linkActivitiesElementList){
		List parseLinkActivitiesList = new ArrayList();
		List group;
		String groupStr;
		for(Element linkActivitiesGroup : linkActivitiesElementList){
			groupStr =  linkActivitiesGroup.getText();
			group = BaseUtil.splitAsList(groupStr, ",");
			parseLinkActivitiesList.add(group);
		}
		return parseLinkActivitiesList ;
	}
}
